package com.sky.gateway.interceptor;

import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;

@Component
@Slf4j
@RequiredArgsConstructor
public class DynamicRoutingConfiguration {

    private final NacosConfigManager nacosConfigManager;
    private final RouteDefinitionWriter writer;

    private final String NacosId = "gateway-routers.json";
    private final String GroupId = "sky-take-out";

    private final Set<String> routeIds = new HashSet<>();

    @PostConstruct
    public void initConfiguration() throws NacosException {
        String config = nacosConfigManager.getConfigService()
                .getConfigAndSignListener(NacosId, GroupId, 5000, new Listener() {

                    @Override
                    public Executor getExecutor() {
                        return null;
                    }

                    // 更新路由表
                    @Override
                    public void receiveConfigInfo(String s) {
                        updateConfigInfo(s);
                    }


                });
        // 更新路由表
        updateConfigInfo(config);
    }

    private void updateConfigInfo(String s) {
        log.info("update config info : {}", s);
        // 1.解析配置信息为RouteDefinition
        List<RouteDefinition> routeDefinitions = JSONUtil.toList(s, RouteDefinition.class);
        // 2.删除旧的路由表
        routeIds.forEach(routeDefinition ->{
            writer.delete(Mono.just(routeDefinition)).subscribe();
        });
        routeIds.clear();
        // 3.更新路由表
        routeDefinitions.forEach(routeDefinition -> {
            writer.save(Mono.just(routeDefinition)).subscribe();
        });
    }

}
